package com.ruoyi.system.service.impl;

import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.TreeSelect;
import com.ruoyi.common.core.domain.entity.CustomMultipartFile;
import com.ruoyi.common.core.domain.entity.File;
import com.ruoyi.common.core.domain.entity.FileVersion;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.server.MinioService;
import com.ruoyi.system.mapper.FileMapper;
import com.ruoyi.system.mapper.FileVersionMapper;
import com.ruoyi.system.service.FileAuthRefService;
import com.ruoyi.system.service.FileService;
import com.ruoyi.system.service.ISysRoleService;
import com.ruoyi.util.SnowFlakeIdWorker;
import io.jsonwebtoken.lang.Assert;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.core.io.AbstractResource;
import org.springframework.http.*;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ObjectUtils;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

@Service
//@AllArgsConstructor
@Slf4j
public class FileServiceImpl implements FileService {

    @Autowired
    private FileMapper fileMapper;

    @Autowired
    private FileVersionMapper fileVersionMapper;

    @Autowired
    private ISysRoleService sysRoleService;



    @Autowired
    private FileAuthRefService fileAuthRefService;

    private final SnowFlakeIdWorker worker = new SnowFlakeIdWorker(2,2);

    @Autowired
    private MinioService minioService;

    @Value("${ai.address}")
    private String ragflowAddress;

    @Value("${ai.your_api_key}")
    private String ragflowApiKey;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public AjaxResult renameFile(Long id, String fileName, String label) {
        System.out.println("servicewenjian"+ id);
        // 1. 获取文件信息
        File file = fileMapper.selectFileById(id);
        System.out.println("文件信息;         "+     file               );
        if (file == null) {
            throw new ServiceException("文件不存在或已被删除");
        }
        System.out.println("fa"+    file);

        // 3. 验证名称冲突
        Integer conflictCount = fileMapper.checkNameConflict(
                file.getParentId(),
                fileName,
                label,
                id
        );

        if (conflictCount > 0) {
            return AjaxResult.error("名称已存在");
        }

        // 4. 更新文件记录
        int updateCount = fileMapper.updateFileNameAndLabel(
                id,
                label,
                label,
                SecurityUtils.getUsername()
        );
        if (updateCount == 0) {
            throw new ServiceException("更新失败，请检查文件状态");
        }
        return AjaxResult.success();
    }

    @Override
    public File selectFileById(Long id) {
        return fileMapper.selectFileById(id);
    }

    @Override
    public File findByFileName(String fileName) {
        // 这里可以调用 Mapper 方法执行自定义查询
        return null;
    }

    @Override
    public List<TreeSelect> selectFileTreeList() {
        Long userId = SecurityUtils.getUserId();
        Assert.notNull(userId, "请登录");
        File file = new File().setType(1);
        // 数据库查出所有的文件
        List<File> files = fileMapper.selectFiles(file);
        // 对文件进行排序
        List<File> fileTrees = buildFileTree(files);
        return fileTrees.stream()
                .map(TreeSelect::new)
                .collect(Collectors.toList());
    }

    /**
     * 把所有文件、文件夹结构查询出来
     * @return
     */
    @Override
    public List<TreeSelect> selectAllFileTreeList() {
        Long userId = SecurityUtils.getUserId();
        Assert.notNull(userId, "请登录");
        //查询出所有的角色
        List<Long> roleIds = sysRoleService.selectRoleListByUserId(userId);
        if (ObjectUtils.isEmpty(roleIds)){
            roleIds = new ArrayList<>();
        }
        File file = new File();
        // 数据库查出所有的文件
        List<File> files = fileMapper.selectFilesWithPermission(roleIds,userId,file);
        // 对文件进行排序
        List<File> fileTrees = buildFileTree(files);
        return fileTrees.stream()
                .map(TreeSelect::new)
                .collect(Collectors.toList());
    }


    /**
     * 获取文件列表
     * @param file
     * @return
     */
    @Override
    public List<File> selectList(File file) {
        //构建查询条件
        Long userId = SecurityUtils.getUserId();
        Assert.notNull(userId, "请登录");
//        file.setUserId(userId);
        if (file.getParentId() == null) {
            file.setParentId(0L);
        }
        //查询
        List<File> files = fileMapper.selectFiles(file);
        return files;
    }

    /**
     * 将所有的部门进行从新整合，构建文件树
     * @param files
     * @return
     */
    public List<File> buildFileTree(List<File> files) {
        // 使用 Map 存储每个部门的所有子部门，避免重复遍历列表
        Map<Long, List<File>> fileMap = files.stream()
                .collect(Collectors.groupingBy(File::getParentId));
        // 定义根节点
        File root = new File().setId(0L).setFileName("基础文件夹");
        for (File file : files) {
            if (file.getId() == 0L){
                root = file;
            }
        }

        // 递归构建树
        buildDeptSubTree(fileMap, root);
        return Collections.singletonList(root);
    }

    /**
     *  构建子部门树
     */
    private void buildDeptSubTree(Map<Long, List<File>> fileMap, File parent) {
        List<File> children = fileMap.get(parent.getId());
        if (children != null) {
            parent.setChildren(children);
            children.forEach(child -> buildDeptSubTree(fileMap, child));  // 递归处理子部门
        }
    }

    /**
     * 文件上传
     * @param files 文件对象
     * @param parentId
     * @throws IOException
     */
    @Override
    @Transactional
    public void uploadFile(MultipartFile[] files, Long parentId,Integer security, String datasetId) throws IOException {

        //文件冲突检测 TODO

        //用于接收上传后的数据
        List<String> filesNames = new ArrayList<>();
        List<File> fileslist = new ArrayList<>();
        List<FileVersion> filesVersionlist = new ArrayList<>();
        HashMap<String,List<Long>> floderNames = new HashMap<>();  //上传的文件夹名称,以及id
        Map<String, String> map = null;

        List<String> documentIds = new ArrayList<>(); // 存储上传成功的文档ID

        // 用于后续查找或创建父文件夹
        File father;

        // 如果parentId不为0，表示需要查找特定父文件夹
        if (parentId != 0){
            // 使用fileMapper根据parentId选择文件列表
            List<File> fathers = fileMapper.selectFiles(new File().setId(parentId));

            // 确保查询结果不为空，如果为空则抛出异常，提示文件系统错误
            Assert.isTrue(fathers.size() > 0, "文件系统错误，请重新再试");

            // 从查询结果中获取第一个文件作为父文件夹
            father = fathers.get(0);
        }else {
            // 如果parentId为0，创建一个新的File对象并设置其ID为0，表示根目录
            father = new File().setId(0L);
        }
        try {
            // 初始化当前父ID
            Long currentParentId = parentId;
            //构建当前文件路径
            StringBuilder currentFilePath = new StringBuilder();
            // 如果父ID为0，则表示这是根路径，否则在路径前加上父文件的祖先路径
            currentFilePath.append(parentId == 0 ? "":father.getAncestors()+",");
            // 加上当前文件或文件夹的ID
            currentFilePath.append(father.getId());
            // 遍历每个上传的文件
            for (MultipartFile file : files){
                // 对于每个文件，重置当前父ID为原始父ID
                currentParentId = parentId;
                // 分割文件名以获取文件路径 components
                String[] split = file.getOriginalFilename().split("/");
                // 获取完整的文件路径
                String filePath = file.getOriginalFilename();
                // 获取纯文件名，即路径的最后一部分
                String fileName = split[split.length-1];
                //考虑文件夹情况 ,构建逻辑文件夹
                if (split.length > 1){
                    // 如果路径 components 大于1，表示需要创建逻辑文件夹
                    for (int i = 0 ; i < split.length-1; i++){
                        // 如果当前文件夹名不在已创建的文件夹中，则创建新文件夹
                        if (!floderNames.containsKey(split[i])) {
                            long id = worker.nextId();
                            floderNames.put(split[i], Arrays.asList(id, currentParentId));
                            // 在当前文件路径中添加新创建的文件夹ID
                            currentFilePath.append(",");
                            currentFilePath.append(id);
                            // 更新当前父ID为新创建的文件夹ID
                            currentParentId = id;
                        }
                    }
                    // 获取当前文件所在逻辑文件夹的ID
                    currentParentId = floderNames.get(split[split.length-2]).get(0);
                }

                // 构建保存对象
                File fileEntity = new File();
                FileVersion fileVersion = new FileVersion();

                // 查询是否存在文件覆盖
                File base = new File().setUserId(SecurityUtils.getUserId()).setLabel(fileName).setParentId(parentId);
                List<File> existingFile = Optional.ofNullable(fileMapper.selectFiles(base)).orElse(new ArrayList<>());
                // 构建版本信息
                FileVersion latestVersion;
                if (!CollectionUtils.isEmpty(existingFile)) { // 存在文件覆盖
                    fileEntity = existingFile.get(0);
                    latestVersion = fileVersionMapper.findLatestVersionByFileId(fileEntity.getId());
                } else {
                    latestVersion = null;
                    // 如果不存在文件覆盖，则设置文件的基本信息
                    fileEntity.setParentId(currentParentId)
                            .setUserId(SecurityUtils.getUserId())
                            .setFileName(fileName)
                            .setFileSize(file.getSize());
                }
                // 计算新版本号
                int newVersion = (latestVersion != null) ? latestVersion.getVersion() + 1 : 1;

                //文件上传
                map = minioService.uploadFile(file, fileName);
                if (map == null || map.get("success") == null) {
                    throw new IOException("文件上传失败");
                }

                // RAGFlow文件上传
                String documentId = uploadToRAGFlow(file, datasetId);

                documentIds.add(documentId);

                if(ObjectUtils.isEmpty(fileEntity.getId())){
                    fileEntity.setId(worker.nextId());
                }

                // 更新文件实体
                String[] split1 = file.getContentType().split("\\.");
                fileEntity.setFileSize(file.getSize())
                        .setFileType(getFileType(fileName))
                        .setUploadUser(SecurityUtils.getUsername())
                        .setUserId(SecurityUtils.getUserId())
                        .setFilePath(map.get("fileUrl"))
                        .setType(0)
                        .setFileSize(file.getSize())
                        .setUploadTime(new Date())
                        .setFileName(fileName)
                        .setLabel(fileName)
                        .setIsDeleted(0)
                        .setSecurity(security)
                        .setAncestors(currentFilePath.toString());

                // 最后进行版本管理设置
                fileVersion.setId(worker.nextId())
                        .setFileId(fileEntity.getId()) // 确保使用正确的文件ID
                        .setVersion(newVersion)
                        .setCreatedTime(new Date())
                        .setMark("")
                        .setSubmitter(SecurityUtils.getUsername())
                        .setFilePath(map.get("fileUrl"));
//                filesNames.add(map.get("fileName"));
                fileslist.add(fileEntity);
                filesVersionlist.add(fileVersion);
            }
            //批量构建文件夹逻辑对象  带有文件夹上传
            if (!floderNames.isEmpty()) {
                for (Map.Entry<String, List<Long>> entry : floderNames.entrySet()) {
                    File fileEntity = new File();
                    fileEntity.setId(entry.getValue().get(0))
                            .setParentId(entry.getValue().get(1))
                            .setUserId(SecurityUtils.getUserId())
                            .setFileName(entry.getKey())
                            .setLabel(entry.getKey())
                            .setUploadTime(new Date())
                            .setFileSize(0L)
                            .setAncestors(String.valueOf(entry.getValue().get(1)))
                            .setFileType("folder")
                            .setType(1)
                            .setIsDeleted(0)
                            .setSecurity(security)
                            .setUploadUser(SecurityUtils.getUsername());
                    fileslist.add(fileEntity);
                }
                // 保存记录
                fileMapper.batchInsertFile(fileslist);
            }else {
                //更新记录
                fileMapper.realDeleteFile(fileslist.get(0).getId());
                fileMapper.batchInsertFile(fileslist);
            }

            fileVersionMapper.batchInsertFileVersion(filesVersionlist);

            // 解析文档
            parseDocumentsAsync(datasetId, documentIds);
        } catch (Exception e) {
            if (map != null){
                for (String fileName : filesNames){
                    minioService.deleteFile("zhishiku", fileName);
                }
            }
            // 异常时清理已上传文档
            if (!documentIds.isEmpty()) {
                deleteDocuments(datasetId, documentIds);
            }
            log.error("文件操作失败: {}", e.getMessage(), e);
            throw new IOException("文件操作失败: " + e.getMessage(), e);
        }
    }

   /**传文件成功后，调用解析方法。解析方法需要异步执行，
    * 并处理可能的异常，在异常时删除文档。
    * 同时，需要存储解析任务的状态，以便前端查询。
    前端方面，上传文件后，启动轮询，每隔几秒查询任务状态，直到解析完成或失败，更新进度条或显示错误 */

    // 上传到ragflow 知识库中
    private String uploadToRAGFlow(MultipartFile file, String datasetId) throws IOException {
        String url = ragflowAddress + "/api/v1/datasets/" + datasetId + "/documents";

        System.out.println("------------上传到ragflow 知识库中-------------" + file    +" id :"   +datasetId);

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);
        headers.set("Authorization", ragflowApiKey);

        MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
        body.add("file", new MultipartFileResource(file));
        body.add("parser_config", "{\"chunk_token_num\": 500, \"delimiter\": \"\\n\"}");

        // 增加请求日志
        log.debug("Using RAGFlow API Key: {}", ragflowApiKey);

        try {
            // 使用RestTemplate发起POST请求，并获取响应
            ResponseEntity<Map<String, Object>> response = new RestTemplate().exchange(
                    url,
                    HttpMethod.POST,
                    new HttpEntity<>(body, headers),
                    new ParameterizedTypeReference<Map<String, Object>>() {}
            );

            // 增加完整响应日志
            log.debug("RAGFlow response: Status={}, Body={}",
                    response.getStatusCode(),
                    response.getBody());

            log.debug("开始上传文件到数据集 {} | 文件名: {} | 大小: {} bytes",
                    datasetId, file.getOriginalFilename(), file.getSize());


            if (response.getStatusCode().is2xxSuccessful()) {
                Map<String, Object> body1 = response.getBody();
                if (body1 != null && "0".equals(String.valueOf(body1.get("code")))) {
                    List<Map<String,Object>> data = (List<Map<String,Object>>) body1.get("data");
                    if (!CollectionUtils.isEmpty(data)) {
                        return data.get(0).get("id").toString();
                    }
                }
            }
            throw new IOException("RAGFlow上传失败: " + response.getStatusCode());
        } catch (RestClientException e) {
            throw new IOException("RAGFlow请求异常: " + e.getMessage(), e);
        }
    }

    // 新增异步解析方法
    @Async
    public CompletableFuture<Void> parseDocumentsAsync(String datasetId, List<String> documentIds) {
        return CompletableFuture.runAsync(() -> {
            try {
                // 调用解析接口
                String parseUrl = ragflowAddress + "/api/v1/datasets/" + datasetId + "/chunks";
                HttpHeaders headers = new HttpHeaders();
                headers.setContentType(MediaType.APPLICATION_JSON);
                headers.set("Authorization", ragflowApiKey);

                Map<String, Object> requestBody = Collections.singletonMap("document_ids", documentIds);

                ResponseEntity<Map> response = new RestTemplate().postForEntity(
                        parseUrl,
                        new HttpEntity<>(requestBody, headers),
                        Map.class
                );

                if (!response.getStatusCode().is2xxSuccessful() ||
                        !"0".equals(String.valueOf(response.getBody().get("code")))) {
                    throw new RuntimeException("解析请求失败");
                }

                // TODO: 这里添加轮询解析状态的逻辑（需要RAGFlow提供状态接口）

            } catch (Exception e) {
                // 解析失败时删除文档
                deleteDocuments(datasetId, documentIds);
                log.error("文档解析失败，已清理上传文件", e);
            }
        });
    }


    // 文档删除实现
    private void deleteDocuments(String datasetId, List<String> documentIds) {
        String url = ragflowAddress + "/api/v1/datasets/" + datasetId + "/documents";

        System.out.println("---------------文档删除实现------------ " + datasetId        +"文档id "+  documentIds);


        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("Authorization", ragflowApiKey);

        Map<String, Object> body = Collections.singletonMap("ids", documentIds);

        new RestTemplate().exchange(
                url,
                HttpMethod.DELETE,
                new HttpEntity<>(body, headers),
                Void.class
        );
    }

    // 辅助类和方法
    private static class MultipartFileResource extends AbstractResource {
        private final MultipartFile file;

        public MultipartFileResource(MultipartFile file) {
            this.file = file;
        }

        @Override
        public String getDescription() {
            return "MultipartFile resource [" + file.getOriginalFilename() + "]";
        }

        @Override
        public String getFilename() {
            return file.getOriginalFilename();
        }

        @Override
        public long contentLength() {
            return file.getSize();
        }

        @Override
        public InputStream getInputStream() throws IOException {
            return file.getInputStream();
        }

        @Override
        public boolean exists() {
            return !file.isEmpty();
        }
    }



    @Override
    public InputStream downloadFile(Long id) throws IOException {
        return null;
    }

    //ToDo 没有做文件冲突处理
    @Override
    public void createFolder(File file) {
        //判断输入条件
        Assert.notNull(file.getParentId(), "父级ID不能为空");
        Assert.notNull(file.getLabel(), "文件夹名称不能为空");
        //找出当前父级文件夹信息
        File father;
        if (file.getParentId() != 0L){
            List<File> fathers = fileMapper.selectFiles(new File().setId(file.getId()));
            Assert.isTrue(fathers.size() > 0, "文件系统错误，请重新再试");
            father = fathers.get(0);
        }else {
            father = new File().setId(0L);
        }
        //构建保存对象
        String currentAncestors = StringUtils.isEmpty(father.getAncestors())? "" : (father.getAncestors()+",") + father.getId();
        file.setId(worker.nextId())
                .setParentId(file.getParentId())
                .setUserId(SecurityUtils.getUserId())
                .setFileName(file.getLabel())
                .setLabel(file.getLabel())
                .setFileSize(0L)
                .setAncestors(currentAncestors)
                .setFileType("folder")
                .setType(1)
                .setIsDeleted(0);
        fileMapper.insertFile(file);
    }

    @Override
    @Transactional
    public void deleteFileOrFolder(Long id) {
        Assert.isTrue(!ObjectUtils.isEmpty(id), "文件ID不能为空");
        //查出当前文件类型
        List<File> files = fileMapper.selectFiles(new File().setId(id));
        List<File> subFiles = new ArrayList<>();
        if (files.size() <= 0){
            return;
        }
        if (files.get(0).getType() == 1){//删除文件夹，及其以下文件
            //擦找其下所有文件
            subFiles = fileMapper.selectFilesByParent(new File().setId(files.get(0).getId()));
        }
        subFiles.add(files.get(0));
        fileMapper.batchDeleteFilesByCondition(subFiles);

        //版本更新 TODO 不是在这里做的
//        List<FileVersion> fileVersions = new ArrayList<>();
//        List<Long> collect = subFiles.stream().map(File::getId).collect(Collectors.toList());
//        //根据fileid查找出所有文件的最高版本号
//        List<FileVersion> versionsByFiles = fileVersionMapper.findHighestVersionsByFileIds(collect);
//        versionsByFiles = Optional.ofNullable(versionsByFiles).orElse(new ArrayList<>()).stream().map(fileVersion1 -> {
//            fileVersion1.setId(worker.nextId());
//            fileVersion1.setVersion(fileVersion1.getVersion() + 1);
//            return fileVersion1;
//        }).collect(Collectors.toList());
//        fileVersionMapper.batchInsertFileVersion(versionsByFiles);
    }

    @Override
    public List selectChildrenFileList(Long id) {
        List<Map> resultList = new ArrayList<>();
        if (ObjectUtils.isEmpty(id)){
            return resultList;
        }
        //查询子文件列表
        List<File> fileList = fileMapper.selectChildrenFileList(id);
        if (ObjectUtils.isEmpty(fileList)){
            return resultList;
        }
        boolean hasChildren = false;
        //转换成前端展示格式
        for (File file : fileList){
            Map<String,Object> map = new HashMap<>();
            map.put("id",file.getId());
            map.put("name",file.getFileName());
            if (file.getType().intValue() == 1)
                hasChildren = true;
            map.put("hasChildren",hasChildren);
            resultList.add(map);
        }
        return resultList;
    }

    @Override
    public boolean checkPremission(Long fileId,Integer authId) {
        boolean premission = false;
        try {
            premission = false;
            List<File> files = new ArrayList<>();
            if ("0".equals(fileId.toString())){
                files.add(new File().setId(0L).setUserId(0L).setSecurity(3));
            }else {
                files = fileMapper.selectFiles(new File().setId(fileId));
            }
            Long userId = SecurityUtils.getUserId();

            if (files.size() > 0){
                //校验主权
                if (files.get(0).getUserId().equals(userId)){
                    return true;
                }
                //校验密级
                Integer security = Optional.ofNullable(SecurityUtils.getSecurity()).orElse(0);
                if (security < files.get(0).getSecurity()){
                    return false;
                }
                //校验权限
                List<Long> fileAuthRefs = fileAuthRefService.selectAllByUserIdAndFileId(userId, fileId,authId);
                if (fileAuthRefs.size() > 0){
                    premission =  true;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return premission;
    }

    public String getFileType(String fileName) {
        if (fileName == null || fileName.isEmpty()) {
            return "other";
        }

        // 获取文件后缀
        String extension = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();

        // 分类规则
        switch (extension) {
            case "jpg":
            case "png":
            case "gif":
            case "bmp":
            case "webp":
                return "image";
            case "mp4":
            case "mov":
            case "avi":
            case "mkv":
                return "video";
            case "txt":
            case "doc":
            case "docx":
            case "pdf":
            case "xls":
            case "xlsx":
            case "ppt":
            case "pptx":
                return "document";
            case "mp3":
            case "wav":
            case "flac":
                return "audio";
            case "zip":
            case "rar":
            case "7z":
            case "tar":
                return "archive";
            case "js":
            case "java":
            case "py":
            case "html":
            case "css":
                return "code";
            default:
                return "other";
        }
    }


    @Override
    @Transactional
    public void saveChange(String downUrl, String changeUrl, String fileId, String userId, String changeTime) throws IOException {
        //查询出该文件信息
        File file = new File().setId(Long.valueOf(fileId));
        List<File> files = fileMapper.selectFiles(file);
        Assert.isTrue(files.size() > 0, "文件不存在");
        List<FileVersion> highestVersions = fileVersionMapper.findHighestVersionsByFileIds(Arrays.asList(Long.valueOf(fileId)));
        File entity = files.get(0);

        //保存新文件
        Map<String, String> map = null;//用于接收文件上传结果
        MultipartFile convert = null;
        try {
            convert = convert(downUrl, entity.getLabel(), null);
            map = minioService.uploadFile(convert, entity.getLabel());
        }catch (Exception e){
            e.printStackTrace();
            log.error("保存文件失败");
        }

        if (map == null || map.get("success") == null) {
            throw new IOException("文件上传失败");
        }
        //删除旧文件
        fileMapper.batchDeleteFilesByCondition(Collections.singletonList(new File().setId(entity.getId())));

        // 构建更新文件实体
        entity.setId(worker.nextId())
                .setFileSize(convert.getSize())
                .setUploadUser(SecurityUtils.getUsername())
                .setUserId(SecurityUtils.getUserId())
                .setFilePath(map.get("fileUrl"))
                .setType(0)
                .setUploadTime(new Date())
                .setFileName(map.get("fileName"))
                .setIsDeleted(0);

        // 最后进行版本管理设置
        Integer newVersion = 0;
        if (highestVersions.size()>0){
            newVersion = highestVersions.get(0).getVersion() + 1;
        }
        FileVersion fileVersion = new FileVersion().setId(worker.nextId())
                .setFileId(entity.getId()) // 确保使用正确的文件ID
                .setVersion(newVersion)
                .setCreatedTime(new Date())
                .setMark("")
                .setSubmitter(SecurityUtils.getUsername())
                .setFilePath(map.get("fileUrl"));

        //保存数据
        fileMapper.insertFile(entity);
        fileVersionMapper.insertFileVersion(fileVersion);
    }



    public static MultipartFile convert(String url, String fileName, String contentType) throws Exception {
        HttpURLConnection connection = null;
        InputStream inputStream = null;
        ByteArrayOutputStream outputStream = null;

        try {
            // 创建URL对象
            URL fileUrl = new URL(url);
            connection = (HttpURLConnection) fileUrl.openConnection();
            connection.setRequestMethod("GET");

            // 获取输入流
            inputStream = connection.getInputStream();
            outputStream = new ByteArrayOutputStream();

            // 读取文件数据
            byte[] buffer = new byte[4096];
            int bytesRead;
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                outputStream.write(buffer, 0, bytesRead);
            }

            // 获取文件字节数据
            byte[] fileBytes = outputStream.toByteArray();

            // 若未提供Content-Type，使用响应头中的值
            if (contentType == null) {
                contentType = connection.getContentType();
                if (contentType == null) {
                    contentType = "application/octet-stream"; // 默认类型
                }
            }

            // 创建并返回MultipartFile
            return new CustomMultipartFile(
                    "file", // 表单字段名
                    fileName,
                    contentType,
                    fileBytes
            );

        } finally {
            // 关闭资源
            if (inputStream != null) {
                inputStream.close();
            }
            if (outputStream != null) {
                outputStream.close();
            }
            if (connection != null) {
                connection.disconnect();
            }
        }
    }
}
